package com.stars.module.holiday.service.impl;

import com.alibaba.fastjson2.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.stars.module.holiday.entity.StarHoliday;
import com.stars.module.holiday.mapper.HolidayMapper;
import com.stars.module.holiday.service.StarHolidayService;
import com.stars.util.common.DevelopKit;
import com.stars.util.date.DateFormatUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class StarHolidayServiceImpl extends ServiceImpl<HolidayMapper, StarHoliday> implements StarHolidayService {

    private final HolidayMapper holidayMapper;

    public StarHolidayServiceImpl(HolidayMapper holidayMapper) {
        this.holidayMapper = holidayMapper;
    }


    @Override
    public List<String> loadHolidayByYear(String year) {

        LambdaQueryWrapper<StarHoliday> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StarHoliday::getYear,year);

        List<StarHoliday> list = Optional.ofNullable(this.list(queryWrapper)).orElse(Collections.emptyList());

        return list.stream().map(StarHoliday::getHoliday).collect(Collectors.toList());
    }

    @Override
    public boolean setHoliday(String date) {

        boolean result;
        if(isHoliday(date)){
            result = holidayMapper.deleteHoliday(date);
        }else{

            Date day = DateFormatUtils.parseDate(date);

            if(day == null){
                return false;
            }

            String year = date.split("-")[0];

            StarHoliday holiday = new StarHoliday();
            holiday.setId(DevelopKit.generateUUID());
            holiday.setHoliday(date);
            holiday.setYear(year);
            holiday.setType(2);
            holiday.setSetDay(day);

            DevelopKit.setBaseInfo(holiday);

            result = holidayMapper.insert(holiday)>0;
        }

        return result;
    }

    @Override
    @Transactional
    public boolean initHolidayByYear(String year) {

        boolean result = false;

        LambdaQueryWrapper<StarHoliday> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper.eq(StarHoliday::getYear,year);

        holidayMapper.deleteHolidayByYear(year);

        Set<String> set = this.getAllWeek(year);
        List<StarHoliday> list = new ArrayList<>();

        StarHoliday holiday;
        for(String day : set){

            holiday = new StarHoliday();
            holiday.setId(DevelopKit.generateUUID());
            holiday.setHoliday(day);
            holiday.setYear(year);
            holiday.setType(1);
            holiday.setSetDay( DateFormatUtils.parseDate(day) );

            DevelopKit.setBaseInfo(holiday);

            list.add(holiday);
        }

        if(list.size()>0){
            result = this.saveBatch(list);// 批量提交
        }

        return result;
    }

    /**
     * 获取区间所有工作日接口
     * @param start yyyy-MM-dd
     * @param end yyyy-MM-dd
     * @return
     */
    @Override
    public JSONArray getWorkDay(String start, String end) {

        Date startDay = DateFormatUtils.parseDate(start);
        Date endDay = DateFormatUtils.parseDate(end);

        if(startDay == null || endDay == null){
            return null;
        }

        return getWorkDay(startDay, endDay);
    }

    @Override
    public JSONArray getWorkDay(Date start, Date end) {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        JSONArray array = new JSONArray();

        JSONArray holidayArray = getHoliday(start, end);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(start);
        String day;

        while (calendar.getTimeInMillis() < end.getTime()){

            day = sdf.format(calendar.getTime());

            if(!holidayArray.contains(day)){
                array.add(day);
            }
            calendar.add(Calendar.DATE,1);
        }

        return array;
    }

    /**
     * 获取区间所有节假日接口
     * @param start yyyy-MM-dd
     * @param end yyyy-MM-dd
     * @return
     */
    @Override
    public JSONArray getHoliday(String start, String end) {

        Date startDay = DateFormatUtils.parseDate(start);
        Date endDay = DateFormatUtils.parseDate(end);

        if(startDay == null || endDay == null){
            return null;
        }

        return getHoliday(startDay, endDay);
    }

    @Override
    public JSONArray getHoliday(Date start, Date end) {

        JSONArray array = new JSONArray();

        LambdaQueryWrapper<StarHoliday> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.ge(StarHoliday::getSetDay, start);
        queryWrapper.le(StarHoliday::getSetDay, end);
        queryWrapper.orderByAsc(StarHoliday::getSetDay);

        List<StarHoliday> list = holidayMapper.selectList(queryWrapper);

        for(StarHoliday holiday: list){
            array.add(holiday.getHoliday());
        }

        return array;
    }

    /**
     * 是否节假日
     * @author : moon
     * @date :  2023/7/13 15:07
     * @param: day 格式 yyyy-MM-dd
     * @return: boolean
     */
    @Override
    public boolean isHoliday(String day) {

        LambdaQueryWrapper<StarHoliday> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper.eq(StarHoliday::getHoliday, day);

        return holidayMapper.exists(queryWrapper);
    }

    @Override
    public boolean isHoliday(Date date) {

        String day = DateFormatUtils.formatDate(date);

        return isHoliday(day);
    }

    /**
     * 全年所有周末
     * @author : moon
     * @date :  2023/7/13 14:59
     * @param: year 年份
     * @return: java.util.Set<java.lang.String>
     */
    private Set<String> getAllWeek(String year) {
        Set<String> set = new HashSet<>();

        int setYear = Integer.parseInt(year);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, setYear);

        int i = 1;
        while (calendar.get(Calendar.YEAR) < setYear+1){
            calendar.set(Calendar.WEEK_OF_YEAR, i++);
            // 周天
            calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
            if(calendar.get(Calendar.YEAR) == setYear){
                set.add(sdf.format(calendar.getTime()));
            }
            // 周六
            calendar.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
            if(calendar.get(Calendar.YEAR) == setYear){
                set.add(sdf.format(calendar.getTime()));
            }
        }

        return set;
    }
}
